<?php

namespace console\controllers;

use console\components\task\TaskMessageManage;
use console\components\task\TaskTimedManage;
use console\components\task\TimeProcess;
use yii\console\Controller;
use console\components\task\TaskManage;
use yii\helpers\Json;

class TaskController extends Controller
{

    private $host = '127.0.0.1';
    private $port = 9503;//执行的时候从params里面获取端口号

    private $config = [
        'worker_num' => 2,
        'daemonize' => 1,
        'group'=>'www',
        'user' => 'www',
        'task_worker_num'=>2,
        'log_file' => DIRECTORY_SEPARATOR.'runtime' . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . 'swoole.log',
        'pid_file' => DIRECTORY_SEPARATOR . 'runtime' . DIRECTORY_SEPARATOR . 'logs' . DIRECTORY_SEPARATOR . 'swoole.pid',
    ];

    public function init()
    {
        $this->config['log_file'] = \Yii::getAlias('@app') . $this->config['log_file'];
        $this->config['pid_file'] = \Yii::getAlias('@app') . $this->config['pid_file'];
    }

    public function actionIndex($message = 'server is running')
    {
//        $server = new \swoole_server($this->host, $this->port);//swoole提供了两种类型的工人:一种负责请求处理，一种负责执行任务。创建一个server实例
////        $server->set([//为server配置参数，设置执行任务工人的数量=4
////            'task_worker_num' => '4',
////           // 'daemonize' => 1
////        ]);
//        $server->set($this->config);
//        $server->on('Start', [$this, 'onStart']);//将处理器绑定在事件上，将onStart绑定在start事件上，一旦start the server，处理器就会执行
//        $server->on('WorkerStart', [$this, 'onWorkerStart']);//将处理器绑定在事件上，将onStart绑定在start事件上，一旦start the server，处理器就会执行
//        $server->on('Receive', [$this, 'onReceive']);//所有自定义的协议将定义在onReceive中
//        $server->on('Task', [$this, 'onTask']);
//        $server->on('Finish', [$this, 'onFinish']);
//        $server->start();// start our server, listen on port and ready to accept connections
        $this->actionStart();
    }

    public function actionStart($message = 'server is running')
    {
        $this->port = \Yii::$app->params['swooleTaskPort'];

        $server = new \swoole_server($this->host, $this->port);
        $server->set($this->config);
        $server->on('Start', [$this, 'onStart']);//将处理器绑定在事件上，将onStart绑定在start事件上，一旦start the server，处理器就会执行
        $server->on('WorkerStart', [$this, 'onWorkerStart']);//将处理器绑定在事件上，将onStart绑定在start事件上，一旦start the server，处理器就会执行
        $server->on('Receive', [$this, 'onReceive']);//所有自定义的协议将定义在onReceive中
        $server->on('Task', [$this, 'onTask']);
        $server->on('Finish', [$this, 'onFinish']);
        $server->start();
    }

    public function onStart($server)
    {
        $server_name = \Yii::$app->params['swooleTaskName'];
        cli_set_process_title($server_name);
        echo '[' . \Yii::$app->formatter->asDatetime(time()) . ']' . \SWOOLE_VERSION . " onStart" . PHP_EOL;
    }

    public function onWorkerStart($server,$worker_id)
    {
        swoole_set_process_name("task_worker");
        if($worker_id==0){
            $server->tick(60000, function() use ($server) {
                TimeProcess::filterTime();//这一part看不懂啊什么时间啊等等等
            });
        }
    }

    public function onReceive($server, $fd, $from_id, $data)
    {
        if (TaskManage::checkTask($data)) {
            $server->task($data);
        }
    }

    public function onTask($server, $task_id, $from_id, $data)
    {
        //\Yii::error('taskcontroller onTask function start...');
        \Yii::$app->db->close();
        TaskManage::addTask($data);
        $server->finish($data);
    }

    public function onFinish($server, $task_id, $data)
    {
        //\Yii::error('taskcontroller onFinish function end...');
        echo "Task {$task_id} finish\n";
        echo "Result: {$data}\n";
    }



    public function actionRestart()
    {
        if($pid = $this->getPid()){
            $pid = $this->sendSignal(SIGTERM);
            $time = 0;
            while (posix_getpgid($pid) && $time <= 10) {
                usleep(30000);
                $time++;
            }
            if ($time > 100) {
                $this->stdout('timeout' . PHP_EOL);
                exit(1);
            }
            $this->actionStart('server restart success');
        }else{
            $this->actionStart('server restart success');
        }

    }

    public function actionStop()
    {
        if (is_numeric($this->getPid())) {
            $this->sendSignal(SIGTERM);
            $this->stdout("server is stopped, stop listening {$this->host}:{$this->port}" . PHP_EOL);
        }
    }

    private function sendSignal($sig)
    {
        if ($pid = $this->getPid()) {
            posix_kill($pid, $sig);
        } else {
            $this->stdout("server is not running!" . PHP_EOL);
            exit(1);
        }
    }

    private function getPid()
    {
        $pid_file = $this->config['pid_file'];
        if (file_exists($pid_file)) {
            $pid = file_get_contents($pid_file);
            if (posix_getpgid($pid)) {
                return $pid;
            } else {
                unlink($pid_file);
            }
        }
        return false;
    }

}